package cn.itsource.basic.service.Impl;

import cn.itsource.basic.constant.WeChatConstant;
import cn.itsource.basic.dto.AdminLoginDto;
import cn.itsource.basic.dto.BinderAccountDto;
import cn.itsource.basic.dto.CodeDto;
import cn.itsource.basic.dto.UserSmsCodeDto;
import cn.itsource.basic.exception.BusinessException;
import cn.itsource.basic.service.ILoginService;
import cn.itsource.basic.util.AjaxResult;
import cn.itsource.basic.util.HttpClientUtils;
import cn.itsource.basic.util.MD5Utils;
import cn.itsource.basic.util.StrUtils;
import cn.itsource.basic.vo.AdminLoginVo;
import cn.itsource.org.domain.Logininfo;
import cn.itsource.org.domain.User;
import cn.itsource.org.domain.Wxuser;
import cn.itsource.org.mapper.LogininfoMapper;
import cn.itsource.org.mapper.WxuserMapper;
import cn.itsource.org.service.impl.UserServiceImpl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class LoginServiceImpl implements ILoginService {

    @Autowired
    private WxuserMapper wxuserMapper;
    @Autowired
    private LogininfoMapper logininfoMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private UserServiceImpl userService;

    /**
     * 用户登录
     * @param adminLoginDto
     * @return ajaxResult
     */

    @Override
    public AjaxResult login(AdminLoginDto adminLoginDto) {
        Integer type = adminLoginDto.getType();
        String username = adminLoginDto.getUsername();
        String password = adminLoginDto.getPassword();
        //loadByConditions:mapper.xml sql语句中包含用户名,邮箱,电话,且需要指定type
        Logininfo logininfo = logininfoMapper.loadByConditions(username,type);
        if (logininfo == null){
            throw new BusinessException("用户不存在");
        }
        //对比密码是否正确
        String pwdInDB = logininfo.getPassword();
        String salt = logininfo.getSalt();

        String pwdInBrowse = MD5Utils.encrypByMd5(password + salt);
        if (!pwdInDB.equals(pwdInBrowse)){
            throw new BusinessException("用户名或密码不正确");
        }
        //生成uuid作为redis中存储的key,保存redis
        String token = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set(token,logininfo,30, TimeUnit.MINUTES);

        AdminLoginVo adminLoginVo = new AdminLoginVo();
        adminLoginVo.setToken(token);
        adminLoginVo.setLogininfo(logininfo);

        logininfo.setSalt(null);
        logininfo.setPassword(null);

        return AjaxResult.me().setResultObj(adminLoginVo);

    }

    /**
     * 三方登录
     * @param codeDto
     * @return
     */
    @Override
    public AjaxResult wechatLogin(CodeDto codeDto) {
        String code = codeDto.getCode();

        //去请求微信发个code过来
        String requestUrl = WeChatConstant.GET_TOKEN_OPENID_URL
                .replace("APPID",WeChatConstant.APPID)
                .replace("SECRET",WeChatConstant.SECRET)
                .replace("CODE",code);

        //通过code去拿含有token,openId的路径
        String responseUrlStr = HttpClientUtils.httpGet(requestUrl);
        JSONObject responseUrlJsonObj = JSON.parseObject(responseUrlStr);

        //拿到access_token(token)和openid(openId)
        String access_token = responseUrlJsonObj.getString("access_token");
        String openId = responseUrlJsonObj.getString("openid");

        //通过openId查数据库wxuser表有没有该用户
        Wxuser wxuser = wxuserMapper.loadByOpenid(openId);
        //用户不存在,去绑定
        if (wxuser == null){
            //拼接绑定页面返回前端
            String binderUrl = "?token="+access_token+"&openid="+openId;
            return AjaxResult.me().setSuccess(false).setResultObj(binderUrl);
        }
        //用户存在
        //通过userId查用户登录信息-->登录信息需要存在redis作为value
        /*
        wxuser对象中可以拿到userId
        logininfo可以用userId查
         */
        Logininfo logininfo = logininfoMapper.loadByUserId(wxuser.getUserId());
        //生成uuid作为redis中存储的key,保存redis
        String token = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set(token,logininfo,30, TimeUnit.MINUTES);

        AdminLoginVo adminLoginVo = new AdminLoginVo();
        adminLoginVo.setToken(token);
        adminLoginVo.setLogininfo(logininfo);

        logininfo.setSalt(null);
        logininfo.setPassword(null);
        //给前端返回
        return AjaxResult.me().setResultObj(adminLoginVo);
    }

    /**
     * wxuser表中没有,跳到绑定接口
     * @param binderAccountDto
     * @return
     */
    @Override
    public AjaxResult binder(BinderAccountDto binderAccountDto) {
        String accessToken = binderAccountDto.getAccessToken();
        String openId = binderAccountDto.getOpenId();
        String phone = binderAccountDto.getPhone();
        String password = binderAccountDto.getPassword();

        Wxuser wxuser = wxuserMapper.loadByOpenid(openId);
        //在wxuser表查到
        if (wxuser != null){
            throw new BusinessException("禁止重复绑定同一微信!");
        }
        //没查到还用微信登录,人畜无害的新人一枚吖~
        //去获取微信用户信息保存到wxuser表
        String wechatInfoUrl = WeChatConstant.GET_WECHAT_INFO_URL
                .replace("ACCESS_TOKEN",accessToken)
                .replace("OPENID",openId);

        String resultStr = HttpClientUtils.httpGet(wechatInfoUrl);
        JSONObject resultJsonObject = JSON.parseObject(resultStr);

        //注册
        //加密   --->加盐加密
        String salt = StrUtils.getComplexRandomString(16);
        String pwdInDB = MD5Utils.encrypByMd5(password + salt);
        
        UserSmsCodeDto userSmsCodeDto = new UserSmsCodeDto();
        userSmsCodeDto.setPhone(phone);

        //保存logininfo
        Logininfo logininfo = userService.saveLogininfo(userSmsCodeDto, salt, pwdInDB);
        //保存user
        User user = userService.logininfo2User(logininfo);
        //保存wxuser
        saveWxuser(openId, resultJsonObject, user);

        //生成uuid作为redis中存储的key,保存redis
        String token = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set(token,logininfo,30, TimeUnit.MINUTES);

        AdminLoginVo adminLoginVo = new AdminLoginVo();
        adminLoginVo.setToken(token);
        adminLoginVo.setLogininfo(logininfo);

        logininfo.setSalt(null);
        logininfo.setPassword(null);
        //给前端返回
        return AjaxResult.me().setResultObj(adminLoginVo);

    }

    //保存wxuser的方法
    private void saveWxuser(String openId, JSONObject resultJsonObject, User user) {
        Wxuser wxusernew = new Wxuser();
        wxusernew.setOpenid(openId);
        wxusernew.setNickname(resultJsonObject.getString("nickname"));
        wxusernew.setAddress(resultJsonObject.getString("country"));
        wxusernew.setHeadimgurl(resultJsonObject.getString("headimgurl"));
        wxusernew.setSex(resultJsonObject.getInteger("sex"));
        wxusernew.setUserId(user.getId());
        wxuserMapper.save(wxusernew);
    }
}
